
/*
 * 	RegMask.cpp create 2009-11-20
 * 		by ws
 */

#include<iostream>
#include<vector>
#include"common.hpp"
#include"RegMask.hpp"


bool operator & (RegMask & x, RegMask &y)
{
	for(int i = 0; i < RegMask::mask_lenth ; i++)
	{
		if(x.mask[i] & y.mask[i])
			return true;
	}
	return false;
}

bool operator | (RegMask &x, RegMask &y)
{
	for(int i = 0; i < RegMask::mask_lenth; i++)
	{
		if(x.mask[i] | y.mask[i])
			return true;
	}
	return false;
}


RegMask::RegMask() {
	mask = new unsigned int[mask_lenth];
	for(int i = 0; i < mask_lenth; i++)
	{
		mask[i] = 0;
	}
}


RegMask & RegMask::operator |= (const RegMask& regs)
{
	_union_add(*this, regs);
	return *this;
}

void RegMask::_union_add(RegMask &x, const RegMask &y)
{
	for(int i = 0; i < mask_lenth; i++)
	{
		x.mask[i] |= y.mask[i];
	}
}

void RegMask::add_reg(TargetInfo::PhysicalRegister reg)
{
	int index = reg/32;
	int mod = reg % 32;
	unsigned int m = 1;
	m <<= mod;
	mask[index] |= m;
}

void RegMask::sub_reg(enum TargetInfo::PhysicalRegister reg)
{
	int index = reg/32;
	int mod = reg % 32;
	unsigned int m = 1;
	m<<=mod;
	m = ~m;
	mask[index] &= m;
}

bool RegMask::test_reg(enum TargetInfo::PhysicalRegister  reg)
{
	int index = reg / 32;
	int mod = reg % 32;
	unsigned int m = 1;
	m <<= mod;
	return mask[index] & m;
}

RegMask::~RegMask()
{
	delete[] mask;
}



int RegMask::get_allowed_addr_reg(enum Core c)
{
	assert( c >= MU_U && c < MU_W);
	unsigned int x = mask[8 + c - MU_U];
	x = ~x;
	if( x = 0)
		return -1;
	int reg = 64 * 4;
	while(x % 2 != 1)
	{
		x>>=1;
		reg++;
	}
	return reg;
}


int  RegMask::get_allowed_data_reg(enum Core c)
{
	assert( c >= CORE_X && c <= CORE_T);
	unsigned int low = mask[2 * c];
	unsigned int high = mask[2* c + 1];
	low = ~low;
	high = ~high;
	int reg = 2 * c * 32;
	if(low != 0)
	{
		while(low % 2 != 1)
		{
			low >>= 1;
			reg++;
		}
		return reg;
	}else if(high != 0)
	{
		reg += 32;
		while(high % 2 != 1)
		{
			high >>= 1;
			reg++;
		}
		return reg;
	}else
	{
		return -1;
	}
}


std::vector<int> RegMask::get_allowed_simd_reg()
{
	unsigned int regs[8];
	for(int i = 0; i < 8; i++)
	{
		regs[i] = ~mask[i];
	}
	std::vector<int> ret(8);
	for(int i = 0; i < 4; i++)
	{
		ret[2*i] = 64 * i;
		ret[2*i + 1 ] = 64 * i + 1;
	}
	int count = 0;
	bool ok = false;
	bool end = false;
	//first check the low
	while(!ok && !end)
	{
		ok = true;
		for(int i = 0; i < 4; i++)
		{
			if(regs[2*i] == 0)
			{
				end = true;
				ok  = false;
				break;
			}
			if(regs[2*i] % 4 != 3)
			{
				ok = false;
				break;
			}
		}
		if(end == true)
			break;
		if(ok == true)
			break;
		for(int i = 0; i < 4; i++)
		{
			regs[2*i]>>=2;
		}
		count++;
	}
	while(!ok && !end)
	{
		ok = true;
		for(int i = 0; i < 4; i++)
		{
			if(regs[2*i+1] == 0)
			{
				end = true;
				ok  = false;
				break;
			}
			if(regs[2*i+1] % 4 != 3)
			{
				ok = false;
				break;
			}
		}
		if(end == true)
			break;
		if(ok == true)
			break;
		for(int i = 0; i < 4; i++)
		{
			regs[2*i+1]>>=2;
		}
		count++;
	}
	if(!ok)
	{
		ret.clear();
		ret.size();
		return ret;
	}
	for(int i = 0; i < 8 ; i++)
	{
		ret[i] += count*2;
	}
	return ret;
}
